package com.apexedu.portal.util.umail.bjxml.xstream.converter;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

import java.util.*;

/**
 * Created by luchen on 2015-12-23.
 */
public class PojoMapConverter  implements Converter{
    public boolean canConvert(Class clazz)
    {
        String classname = clazz.getName();

        return (classname.indexOf("Map") >= 0) || (classname.indexOf("List") >= 0) || (classname.indexOf("Bean") >= 0);
    }

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context)
    {
        map2xml(value, writer, context);
    }

    protected void map2xml(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
        boolean bMap = true;
        String classname = value.getClass().getName();

        bMap = classname.indexOf("List") < 0;
        Map.Entry entry;
        if (bMap) {
            Map map = (Map)value;
            for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext(); ) {
                entry = (Map.Entry)iterator.next();
                String key = (String)entry.getKey();
                Object subvalue = entry.getValue();
                writer.startNode(key);
                if (subvalue.getClass().getName().indexOf("String") >= 0)
                    writer.setValue((String)subvalue);
                else {
                    map2xml(subvalue, writer, context);
                }
                writer.endNode();
            }
        }
        else {
            Iterator entry1;
            List list = (List)value;
            for (entry1 = list.iterator(); entry1.hasNext(); ) {
                Object subval = entry1.next();
                Object subvalue = subval;
                writer.startNode("child");
                if (subvalue.getClass().getName().indexOf("String") >= 0)
                    writer.setValue((String)subvalue);
                else {
                    map2xml(subvalue, writer, context);
                }
                writer.endNode(); }
        }
    }

    public Map<String, Object> unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
    {
        Map map = (Map)populateMap(reader, context);
        return map;
    }

    protected Object populateMap(HierarchicalStreamReader reader, UnmarshallingContext context) {
        boolean bMap = true;
        Map map = new HashMap();
        List list = new ArrayList();
        while (reader.hasMoreChildren()) {
            reader.moveDown();
            String key = reader.getNodeName();
            Object value = null;
            if (reader.hasMoreChildren())
                value = populateMap(reader, context);
            else {
                value = reader.getValue();
            }
            if (bMap) {
                if (map.containsKey(key))
                {
                    bMap = false;
                    Iterator iter = map.entrySet().iterator();
                    while (iter.hasNext()) {
                        list.add(((Map.Entry)iter.next()).getValue());
                    }
                    list.add(value);
                }
                else {
                    map.put(key, value);
                }
            }
            else {
                list.add(value);
            }
            reader.moveUp();
        }
        if (bMap) {
            return map;
        }
        return list;
    }
}